<?php

namespace app\service\model;

use app\service\Y;
use think\facade\Cache;
use think\facade\Db;

/**
 * 插件表
 */
class AddonModel extends BaseModel
{

    protected $table = 'addon';

    /**
     * 获取单条插件信息
     * @param $condition
     * @param string $field
     * @return array|\think\Model|null
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     */
	public function getAddonInfo($condition, $field = "*")
	{
		$data = json_encode([ $condition, $field ]);
        $key = "addon_getAddonInfo_" . $data;
        $addon_info = Cache::get($key);
		if (!$addon_info) {
            $addon_info = self::field($field)->where($condition)->find();
            Cache::tag("addon")->set($key, $addon_info);
		}
		return $addon_info;
	}


    /**
     * 获取插件列表
     * @param array $condition
     * @param string $field
     * @param string $order
     * @param null $limit
     * @return mixed|\think\Collection
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     */
	public static function getAddonList($condition = [], $field = '*', $order = '', $limit = null): \think\Collection
    {
		$data = json_encode([ $condition, $field, $order, $limit ]);
		$key = "addon_getAddonList_" . $data;
        $addon_list = Cache::get($key);
		if (!$addon_list) {
            $query = self::field($field)->where($condition)->order($order);
            if ($limit) {
                $query = $query->limit($limit);
            }
            $addon_list = $query->select();
            Cache::tag("addon")->set($key, $addon_list);
        }
		return $addon_list;
	}

    /**
     * 获取插件分页列表
     * @param array $condition
     * @param int $page
     * @param int $page_size
     * @param string $order
     * @param string $field
     * @return mixed|\think\Paginator
     * @throws \think\db\exception\DbException
     */
	public function getAddonPageList($condition = [], $page = 1, $page_size = PAGE_LIST_ROWS, $order = '', $field = '*')
	{
		$data = json_encode([ $condition, $page, $page_size, $order, $field ]);
        $key = "addon_getAddonPageList_" . $data;
        $list = Cache::get($key);
		if (!$list) {
            $list = self::field($field)->where($condition)->order($order)->paginate($page_size, ['page' => $page]);
            Cache::tag("addon")->set($key, $list);
		}

		return $list;
	}

    /**
     * 获取未安装的插件列表
     * @return array
     */
	public static function getUninstallAddonList(): array
    {
		
		$dirs = array_map('basename', glob('../addon/*', GLOB_ONLYDIR));
		$addon_names = self::column('name');
		$addons = [];
		foreach ($dirs as $key => $value) {
			if (!in_array($value, $addon_names)) {
				$info_name = '../addon/' . $value . '/config/info.php';
				if (file_exists($info_name)) {
					$info = include_once $info_name;
					$info['icon'] = 'addon/' . $value . '/icon.png';
					$addons[] = $info;
				}
			}
		}
		return $addons;
	}
	
	/*******************************************************************插件安装方法开始****************************************************/
    /**
     * 插件安装
     * @param $addon_name
     * @return \think\response\Json
     */
	public static function install($addon_name): \think\response\Json
    {
		Db::startTrans();
		try {
			// 插件预安装
			if (!self::preInstall($addon_name)) {
				throw new \Exception('安装失败');
			}
			// 安装菜单
			self::installMenu($addon_name);
			// 添加插件入表
			$addon_info = require '../addon/' . $addon_name . '/config/info.php';
			$addon_info['create_time'] = time();
			$addon_info['icon'] = '../addon/' . $addon_name . '/icon.png';
			$check_addon = self::where('name', '=', $addon_info['name'])->find();
			if ($check_addon) {
			    throw new  \Exception('已存在同名插件');
            }
			self::insert($addon_info);
			// 清理缓存
			Cache::tag('addon')->clear();
			Db::commit();
			return Y::success([], '安装成功');
		} catch (\Exception $e) {
			Db::rollback();
			return Y::error('安装失败', ['error_msg' => $e->getMessage()]);
		}
	}

    /**
     * 插件预安装
     * @param $addon_name
     * @return mixed
     */
	private static function preInstall($addon_name)
	{
		$class_name = "addon\\" . $addon_name . "\\event\\Install";
		$install = new $class_name;
        return $install->handle();
	}

    /**
     * 安装插件菜单
     * @param $addon
     * @return bool
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     */
	private static function installMenu($addon): bool
    {
        return AdminAuthorityModel::refreshMenu($addon);
	}
	
	/**************************************************************插件安装结束*********************************************************/
	
	/**************************************************************插件卸载开始*********************************************************/
    /**
     * 卸载插件
     * @param $addon_name
     * @return array|mixed
     */
	public static function uninstall($addon_name)
	{
		Db::startTrans();
		try {
			// 插件预卸载
			if (!self::preUninstall($addon_name)) {
				throw new \Exception('卸载失败');
			}
			// 卸载菜单
			self::uninstallMenu($addon_name);
            // 卸载插件信息
			self::where('name', '=', $addon_name)->delete();
			//清理缓存
			Cache::tag('addon')->clear();
			Db::commit();
			return Y::success([], '卸载成功');
		} catch (\Exception $e) {
			Db::rollback();
			return Y::error('卸载失败', ['error_msg' => $e->getMessage()]);
		}
	}

    /**
     * 插件预卸载
     * @param $addon_name
     * @return mixed
     */
	private static function preUninstall($addon_name)
	{
		$class_name = "addon\\" . $addon_name . "\\event\\UnInstall";
		$install = new $class_name;
        return $install->handle($addon_name);
	}

    /**
     * 卸载插件菜单
     * @param $addon_name
     */
	private static function uninstallMenu($addon_name)
	{
	    AdminAuthorityModel::where('addon', '=', $addon_name)->delete();
	}
	
	/***************************************************************插件卸载结束********************************************************/

	/************************************************************* 安装全部插件 start *************************************************************/

    /**
     * 安装全部插件
     * @return \think\response\Json
     */
    public static function installAllAddon(): \think\response\Json
    {
        $addon_list_result = self::getUninstallAddonList();
        $addon_list = $addon_list_result["data"];
        foreach($addon_list as $k => $v){
            $item_result = self::install($v["name"]);
            if($item_result["code"] < 0)
                return $item_result;

        }
        return Y::success([], '安装完成');
    }
    /************************************************************* 安装全部插件 end *************************************************************/
}